package job

import (
	"reflect"
	"runtime"

	"gitee.com/dayu1985/framework/logging"
)

type JobOption struct {
	FirstRunGoroutine      bool // 首次运行时转后台运行
	ScheduleImediately     bool // 在作业启动前先执行一次
	DoNotGiveUpWhenRunning bool // 允许多次重复执行（即使上次未执行完）
}

type AnyJob struct {
	running bool
	options JobOption

	job func()
}

func NewJob(job func(), options ...JobOption) *AnyJob {

	if len(options) > 1 {
		panic("Can not use multiple option!")
	}

	option := JobOption{}

	for i := range options {
		option = options[i]
	}

	j := &AnyJob{
		job:     job,
		options: option,
	}

	if option.ScheduleImediately {

		logging.Info("[CRON] Schedule Imediately [%v] ...", runtime.FuncForPC(reflect.ValueOf(job).Pointer()).Name())

		if option.FirstRunGoroutine {
			go j.Run()
		} else {
			j.Run()
		}
	}

	return j
}

func (this *AnyJob) Run() {

	if !this.options.DoNotGiveUpWhenRunning && this.running {
		logging.Warn("[CRON] 作业执行中 [%v] 退出...", runtime.FuncForPC(reflect.ValueOf(this.job).Pointer()).Name())
		return
	}

	this.running = true

	defer func() {
		this.running = false
	}()

	this.job()
}
